package com.zx.zxpicture.domain.picture.template;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpStatus;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import com.zx.zxpicture.infrstructure.common.ErrorCode;
import com.zx.zxpicture.infrstructure.exception.BusinessException;
import com.zx.zxpicture.infrstructure.exception.ThrowUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;

@Slf4j
@Service
public class UrlUpload extends PictureUploadTemplate{
    private static final List<String> ALLOW_EXTENSION = Arrays.asList("jpg", "jpeg", "png", "gif", "bmp", "webp");
    /**
     * 图片校验
     * @param inputSource
     * @param <T>
     */
    @Override
    public <T> void validPicture(T inputSource) {
        String fileUrl = (String) inputSource;
        ThrowUtils.throwIf(fileUrl == null, ErrorCode.PARAMS_ERROR, "路径不能为空");
        //1.校验url格式
        try {
            new URL(fileUrl);
        } catch (MalformedURLException e) {
            log.error("图片url格式不满足要求",e);
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"图片url格式不满足要求");
        }
        //2.校验url协议
        if(!fileUrl.startsWith("http:") && !fileUrl.startsWith("https:")){
            log.error("图片url只支持http或https协议：{}",fileUrl);
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"图片url只支持http或https协议");
        }

        //3.发送HEAD请求查看图片是否存在
        HttpResponse response = null;
        try{
            response = HttpUtil.createRequest(Method.HEAD, fileUrl).execute();
            if (response.getStatus() != HttpStatus.HTTP_OK) {
                //图片不存在，直接返回，不需其他判断
                //因为有些图片网站不支持HEAD请求获取图片信息
                return;
            }
            // 4. 校验文件类型
            //拿到文件的类型
            String contentType = response.header("Content-Type");
            if (StrUtil.isNotBlank(contentType)) {
                // 允许的图片类型
                final List<String> ALLOW_CONTENT_TYPES = Arrays.asList("image/jpeg", "image/jpg", "image/png", "image/webp");
                ThrowUtils.throwIf(!ALLOW_CONTENT_TYPES.contains(contentType.toLowerCase()),
                        ErrorCode.PARAMS_ERROR, "图片类型错误");
            }
            //5. 校验文件大小
            String contentLengthStr = response.header("Content-Length");
            if (StrUtil.isNotBlank(contentLengthStr)) {
                long contentLength = Long.parseLong(contentLengthStr);
                final long TWO_m = 2 * 1024 * 1024L; //限制上传到文件的大小为2M
                if (contentLength > TWO_m) {
                    throw new BusinessException(ErrorCode.PARAMS_ERROR, "图片大小不能超过2M");
                }
            }
        }finally {
            //关闭资源
            if(response != null){
                response.close();
            }
        }

    }

    /**
     * 获取文件名
     * @param inputSource
     * @return
     * @param <T>
     */
    @Override
    public <T> String getFileName(T inputSource) {
        String fileUrl = (String) inputSource;
        boolean contains = ALLOW_EXTENSION.contains(FileNameUtil.extName(fileUrl));
        if(contains){
            return FileNameUtil.getName(fileUrl);// 输出 "file.png"
        }
        return FileUtil.mainName(fileUrl) + ".jpg";
    }

    /**
     * 图片写入文件
     * @param inputResource 输入方式
     * @param file 要写入图片的文件
     * @param <T>
     */
    @Override
    public <T> void getFile(T inputResource, File file) {
        String fileUrl = (String) inputResource;
        try {
            HttpUtil.downloadFile(fileUrl,file);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件写入失败");
        }
    }
}
